﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace project1
{
    public partial class Form1 : Form
    {
        private static int NUM_CLUSTERS = 2;
        private static int TOTAL_DATA = 7;
        private static List<Data> SAMPLES = new List<Data>();
        private static List<Data> dataset = new List<Data>();
        private static List<Centroid> centroids = new List<Centroid>();
        public Form1()
        {
            InitializeComponent();
        }

        private void initialize()
        {
            rtb_thongbao.Text = "Centroids initialized at:\n";

            List<double> lst = new List<double>();
            lst.Add(1.0);
            lst.Add(1.0);
            Centroid c = new Centroid(lst);
            centroids.Add(c);

            lst = new List<double>();
            lst.Add(5.0);
            lst.Add(7.0);
            c = new Centroid(lst);
            centroids.Add(c);
            rtb_thongbao.Text += "(" + centroids[0].getElementAt(0).ToString() + "," + centroids[0].getElementAt(1).ToString() + ")\n";
            rtb_thongbao.Text += "(" + centroids[1].getElementAt(0).ToString() + "," + centroids[1].getElementAt(1).ToString() + ")\n";
            return;
        }

        private static void kMeanCluster()
        {
            double bigNumber = Math.Pow(10, 10);
            double minimum = bigNumber;
            double distance = 0.0;
            int sampleNumber = 0;
            int cluster = 0;
            bool isStillMoving = true;
            Data newData = null;
            while (dataset.Count < TOTAL_DATA)
            {
                List<double> lstnewData = new List<double>();
                lstnewData.Add(SAMPLES[sampleNumber].getElementAt(0));
                lstnewData.Add(SAMPLES[sampleNumber].getElementAt(1));
                newData = new Data(lstnewData);
                dataset.Add(newData);
                minimum = bigNumber;

                for (int i = 0; i < NUM_CLUSTERS; i++)
                {
                    distance = dist(newData, centroids[i]);
                    if (distance < minimum)
                    {
                        minimum = distance;
                        cluster = i;
                    }
                }
                newData.cluster(cluster);
                for (int i = 0; i < NUM_CLUSTERS; i++) // duyet toan bo cac cluster
                {
                    double[] totalOfDimensons = new double[newData.getDimension()];
                    int totalInCluster = 0;
                    for (int j = 0; j < dataset.Count; j++)
                    {
                        if (dataset[j].cluster() == i)
                        {
                            totalOfDimensons[0] += dataset[j].getElementAt(0);
                            totalOfDimensons[1] += dataset[j].getElementAt(1);
                            totalInCluster++;
                        }

                    }
                    if (totalInCluster > 0)
                    {
                        centroids[i].setElementAt(0, totalOfDimensons[0] / totalInCluster);
                        centroids[i].setElementAt(1, totalOfDimensons[1] / totalInCluster);
                    }

                }
                sampleNumber++;
            }
            while (isStillMoving)
            {
                for (int i = 0; i < NUM_CLUSTERS; i++)
                {
                    double[] totalOfDimensons = new double[newData.getDimension()];
                    int totalInCluster = 0;
                    for (int j = 0; j < dataset.Count; j++)
                    {
                        if (dataset[j].cluster() == i)
                        {
                            totalOfDimensons[0] += dataset[j].getElementAt(0);
                            totalOfDimensons[1] += dataset[j].getElementAt(1);
                            totalInCluster++;
                        }

                    }
                    if (totalInCluster > 0)
                    {
                        centroids[i].setElementAt(0, totalOfDimensons[0] / totalInCluster);
                        centroids[i].setElementAt(1, totalOfDimensons[1] / totalInCluster);
                    }
                }
                isStillMoving = false;
                for (int i = 0; i < dataset.Count; i++)
                {
                    Data tempData = dataset[i];
                    minimum = bigNumber;
                    for (int j = 0; j < NUM_CLUSTERS; j++)
                    {
                        distance = dist(tempData, centroids[j]);
                        if (distance < minimum)
                        {
                            minimum = distance;
                            cluster = j;
                        }
                    }
                    tempData.cluster(cluster);
                    if (tempData.cluster() != cluster)
                    {
                        tempData.cluster(cluster);
                        isStillMoving = true;
                    }
                }
            }
            return;

        }

        private void createListData()
        {
            List<double> lst = new List<double>();
            lst.Add(1.0);
            lst.Add(1.0);
            Data d = new Data(lst);
            SAMPLES.Add(d);

            lst = new List<double>();
            lst.Add(1.5);
            lst.Add(2.0);
            d = new Data(lst);
            SAMPLES.Add(d);

            lst = new List<double>();
            lst.Add(3.0);
            lst.Add(4.0);
            d = new Data(lst);
            SAMPLES.Add(d);

            lst = new List<double>();
            lst.Add(5.0);
            lst.Add(7.0);
            d = new Data(lst);
            SAMPLES.Add(d);

            lst = new List<double>();
            lst.Add(3.5);
            lst.Add(5.0);
            d = new Data(lst);
            SAMPLES.Add(d);

            lst = new List<double>();
            lst.Add(4.5);
            lst.Add(5.0);
            d = new Data(lst);
            SAMPLES.Add(d);

            lst = new List<double>();
            lst.Add(3.5);
            lst.Add(4.5);
            d = new Data(lst);
            SAMPLES.Add(d);
        }

        private static double dist(Data d, Centroid c)
        {
            double sum = 0.0;
            for (int i = 0; i < d.getDimension(); i++)
            {
                double x = d.getElementAt(i) - c.getElementAt(i);
                sum += (x * x);
            }
            return Math.Sqrt(sum);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            createListData();
            initialize();
            kMeanCluster();
            for (int i = 0; i < NUM_CLUSTERS; i++)
            {
                rtb_thongbao.Text += "Cluster " + i.ToString() + " includes:\n";
                for (int j = 0; j < TOTAL_DATA; j++)
                {
                    if (dataset[j].cluster() == i)
                    {
                        rtb_thongbao.Text += "     (" + dataset[j].getElementAt(0) + ", " +dataset[j].getElementAt(1) +")\n";
                    }
                }
                rtb_thongbao.Text += "\n";
            }
            rtb_thongbao.Text += "Centroids finalized at:\n";
            for (int i = 0; i < NUM_CLUSTERS; i++)
            {
                rtb_thongbao.Text += "     (" + centroids[i].getElementAt(0) + ", " + centroids[i].getElementAt(1)+")\n";
            }
            rtb_thongbao.Text += "\nEND";
        }
    }
}
